package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.gateway.domain.TIotGateway;
import com.ruoyi.gateway.mapper.TIotGatewayMapper;
import com.ruoyi.system.domain.TIotDevice;
import com.ruoyi.system.domain.TIotOperationLog;
import com.ruoyi.system.mapper.TIotDeviceMapper;
import com.ruoyi.system.mapper.TIotOperationLogMapper;
import com.ruoyi.system.service.ITIotDeviceService;
import com.ruoyi.system.service.SendInstructsService;
import com.ruoyi.system.service.TIotOperationLogService;
import com.ruoyi.system.utils.ElectricityMeterUtil;
import com.ruoyi.system.utils.InstructConstant;
import com.ruoyi.system.utils.InstructTypeConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import com.ruoyi.system.service.ITIotDeviceService;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;


/**
 * @Author: R
 * @Description: 自己写
 * @DateTime: 2023/6/4 19:38
 */
@Service
@Slf4j
public class ITIotDeviceServiceImpl extends ServiceImpl<TIotDeviceMapper, TIotDevice>
        implements ITIotDeviceService {

    @Autowired
    private TIotDeviceMapper tIotDeviceMapper;

    @Resource
    private TIotGatewayMapper tIotGatewayMapper;

    @Resource
    SendInstructsService sendInstructsService;

    @Resource
    StringRedisTemplate stringRedisTemplate;


    /**
     * 查询水电设备
     *
     * @param id 水电设备主键
     * @return 水电设备
     */
    @Override
    public TIotDevice selectTIotDeviceById(Long id) {
        return tIotDeviceMapper.selectTIotDeviceById(id);
    }

    /**
     * 查询水电设备列表
     *
     * @param tIotDevice 水电设备
     * @return 水电设备
     */
    @Override
    public List<TIotDevice> selectTIotDeviceList(TIotDevice tIotDevice) {
        return tIotDeviceMapper.selectTIotDeviceList(tIotDevice);
    }

    /**
     * 新增水电设备
     *
     * @param tIotDevice 水电设备
     * @return 结果
     */
    @Override
    public int insertTIotDevice(TIotDevice tIotDevice) {
        return tIotDeviceMapper.insertTIotDevice(tIotDevice);
    }

    /**
     * 修改水电设备
     *
     * @param tIotDevice 水电设备
     * @return 结果
     */
    @Override
    public int updateTIotDevice(TIotDevice tIotDevice) {
        return tIotDeviceMapper.updateTIotDevice(tIotDevice);
    }

    /**
     * 批量删除水电设备
     *
     * @param ids 需要删除的水电设备主键
     * @return 结果
     */
    @Override
    public int deleteTIotDeviceByIds(Long[] ids) {
        return tIotDeviceMapper.deleteTIotDeviceByIds(ids);
    }

    /**
     * 删除水电设备信息
     *
     * @param id 水电设备主键
     * @return 结果
     */
    @Override
    public int deleteTIotDeviceById(Long id) {
        return tIotDeviceMapper.deleteTIotDeviceById(id);
    }

    @Override
    public TIotOperationLog operationElectricity(String operation, Integer id) {
        //id设备id
        TIotDevice tIotDevice = tIotDeviceMapper.selectTIotDeviceById(Long.valueOf(id));//找到设备
        if (tIotDevice == null){
            throw new RuntimeException("不存在该设备");
        }
        String deviceCode = tIotDevice.getEquipmentNumber();
        stringRedisTemplate.opsForValue().set(deviceCode,operation,30, TimeUnit.SECONDS);
        Integer iotGatewayId = tIotDevice.getIotGatewayId();
        Long gatewayId = Long.valueOf(iotGatewayId);
        TIotGateway gatewayVO = tIotGatewayMapper.selectTIotGatewayById(gatewayId);//找到网关
        if (gatewayVO == null){
            throw new RuntimeException("该设备没有任何网关关联它");
        }
        //拿到操作指令
        String address = ElectricityMeterUtil.deviceAddressConvert(deviceCode);

        String ip = "/"+gatewayVO.getIp()+":"+gatewayVO.getPort();

        //获取发送指令
        String instruct =   getInstruct(address,operation);
        if (instruct == null){
            throw new RuntimeException("获取操作指令失败");
        }
//        String instruct = ElectricityMeterUtil.getCompleteInstruct(address,
//                InstructConstant.ELECTRICITY_METER_PULL_INSTRUCT);
        sendInstructsService.sendInstructs(instruct,ip,deviceCode,InstructTypeConstant.getByKey(operation).getValue());
        TIotOperationLog tIotOperationLog=new TIotOperationLog();
        tIotOperationLog.setOperationType(InstructTypeConstant.getByKey(operation).getValue());
        Authentication authentication = SecurityUtils.getAuthentication();
        tIotOperationLog.setOperationUser("admin");
        tIotOperationLog.setDeviceCode(deviceCode);
        tIotOperationLog.setIotCreate(new Date());
        tIotOperationLog.setIotMofify(new Date());
        tIotOperationLog.setSendIp(ip);
        tIotOperationLog.setOperaionContext(instruct);
        return tIotOperationLog;
    }

    @Override
    public void MeterReading() {
        log.info("查出所有的电表设备的余额");
        //查出所有的电表设备的余额
        List<TIotDevice> list = tIotDeviceMapper.selectTIotDeviceList(null);
        for (TIotDevice device : list) {
            //查出网关
            stringRedisTemplate.opsForValue().set(device.getEquipmentNumber(),InstructTypeConstant.E_BALANCE_SETUPA.getKey());
            TIotGateway gatewayVO = tIotGatewayMapper.selectTIotGatewayById(Long.valueOf(device.getIotGatewayId()));
            String address = ElectricityMeterUtil.deviceAddressConvert(device.getEquipmentNumber());
            String ip = "/"+gatewayVO.getIp()+":"+gatewayVO.getPort();
            String instruce = ElectricityMeterUtil.getCompleteInstruct(address, InstructConstant.ELECTRICITY_BALANCE);
            sendInstructsService.sendInstructs(instruce,ip,device.getEquipmentNumber(), InstructTypeConstant.E_BALANCE_SETUPA.getKey());
        }
    }

    private String getInstruct(String address, String operation) {
        if (operation.equals(InstructTypeConstant.E_MAIN_GATE_OFF.getKey())) { //拉闸
            return ElectricityMeterUtil.getCompleteInstruct(address,
                InstructConstant.ELECTRICITY_METER_PULL_INSTRUCT);
        }else if(operation.equals(InstructTypeConstant.E_MAIN_GATE_NO.getKey())){ //合闸
            return ElectricityMeterUtil.getCompleteInstruct(address,
                    InstructConstant.ELECTRICITY_METER_ON_INSTRUCT);
        }

        return null;
    }
}